package com.itita.ww2.utils.channel.google;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * google oauth2
 * access_token refresher
 * @author NorthLan
 *
 */
public class GoogleServerToken {
	private static final Logger logger = LoggerFactory.getLogger(GoogleServerToken.class);
	private String accessToken = "";
	//
	private Builder builder;
	// 
	private ScheduledExecutorService scheduler;
	private Runnable runable;

	private GoogleServerToken(Builder builder) {
		this.builder = builder;
		this.scheduler = Executors.newSingleThreadScheduledExecutor();
		this.runable = new GoogleOAuth2Runable();
	}

	public final void start() {
		scheduler.scheduleWithFixedDelay(runable, 0, builder.expiresIn, TimeUnit.SECONDS);
	}

	public final String getAccessToken() {
		return accessToken;
	}

	class GoogleOAuth2Runable implements Runnable {

		@Override
		public void run() {
			OkHttpClient httpClient = new OkHttpClient.Builder().proxy(builder.proxy).build();
			// @formatter:off
			RequestBody body = new FormBody.Builder()
					.add("client_id", builder.clientId)
					.add("client_secret", builder.clientSecret)
					.add("grant_type", "refresh_token")
					.add("refresh_token", builder.refreshToken)
					.build();
			// @formatter:on
			Request request = new Request.Builder().url(builder.tokenUri).post(body).build();
			try {
				Response response = httpClient.newCall(request).execute();
				if (!response.isSuccessful()) {
					logger.warn("obtain server Access_Token error! code:{}", response.code());
					return;
				}
				JsonObject data = new JsonParser().parse(response.body().string()).getAsJsonObject();
				accessToken = data.get("access_token").getAsString();
				logger.info("obtain: {}", accessToken);
			} catch (IOException e) {
				logger.error(e.getMessage());
			}
		}
	}

	public static class Builder {
		private String tokenUri = "https://www.googleapis.com/oauth2/v4/token";
		private String refreshToken;
		private String clientId;
		private String clientSecret;
		//
		private int expiresIn = 3600;
		// proxy
		private Proxy proxy = Proxy.NO_PROXY;

		public Builder(String refreshToken, String clientId, String clientSecret) {
			this.refreshToken = refreshToken;
			this.clientId = clientId;
			this.clientSecret = clientSecret;
		}

		public Builder setExpiresIn(int expiresIn) {
			this.expiresIn = expiresIn;
			return this;
		}

		public Builder setTokenUri(String uri) {
			this.tokenUri = uri;
			return this;
		}

		public Builder setProxy(String type, String host, int port) {
			this.proxy = new Proxy(Type.valueOf(type.toUpperCase()), new InetSocketAddress(host, port));
			return this;
		}

		public Builder setRefreshToken(String refreshToken) {
			this.refreshToken = refreshToken;
			return this;
		}

		public Builder setClientId(String clientId) {
			this.clientId = clientId;
			return this;
		}

		public Builder setClientSecret(String clientSecret) {
			this.clientSecret = clientSecret;
			return this;
		}

		public GoogleServerToken build() {
			return new GoogleServerToken(this);
		}
	}

	public Builder getBuilder() {
		return builder;
	}
}
